/**
 * \* Created with IntelliJ IDEA.
 * \* User: Administrator
 * \* Date: 2022/3/30
 * \* Time: 20:02
 * \* To change this template use File | Settings | File Templates.
 * \* Description:
 * \
 */
class MyBlockingQueue {
    // 保存数据的本体
    private int[] data = new int[1000];
    // 有效元素个数
    private int size = 0;
    // 队首下标
    private int head = 0;
    // 队尾下标
    private int tail = 0;
    // 专门的锁对象
    private Object locker = new Object();

    // 入队列
    public void put(int value) throws InterruptedException {
        synchronized (locker) {
            if (size == data.length) {
                // 队列满了. 暂时先直接返回.
                // return;
                locker.wait();
            }
            // 把新的元素放到 tail 位置上.
            data[tail] = value;
            tail++;
            // 处理 tail 到达数组末尾的情况
            if (tail >= data.length) {
                tail = 0;
            }
            // tail = tail % data.length;
            size++;  // 千万别忘了. 插入完成之后要修改元素个数
            // 如果入队列成功, 则队列非空, 于是就唤醒 take 中的阻塞等待.
            locker.notify();
        }
    }

    // 出队列
    public Integer take() throws InterruptedException {
        synchronized (locker) {
            if (size == 0) {
                // 如果队列为空, 就返回一个非法值.
                // return null;
                locker.wait();
            }
            // 取出 head 位置的元素
            int ret = data[head];
            head++;
            if (head >= data.length) {
                head = 0;
            }
            size--;
            // take 成功之后, 就唤醒 put 中的等待.
            locker.notify();
            return ret;
        }
    }
}

public class Demo21 {
    private static MyBlockingQueue queue = new MyBlockingQueue();

    public static void main(String[] args) {
        // 实现一个简单的生产者消费者模型
        Thread producer = new Thread(() -> {
            int num = 0;
            while (true) {
                try {
                    System.out.println("生产了: " + num);
                    queue.put(num);
                    num++;
                    // 当生产者生产的慢一些的时候, 消费者就得跟着生产者的步伐走.
                    // Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        producer.start();

        Thread customer = new Thread(() -> {
            while (true) {
                try {
                    int num = queue.take();
                    System.out.println("消费了: " + num);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        customer.start();

    }
}
